package controller;

import gui.JRowItem;
import gui.Main;
import interfaces.ICIA;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.security.PrivateKey;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import api.CAUtils;
import api.CIA;
import api.TerminalUtils;

/**
 * @author hqthai01 Jan 2, 2015
 */
public class BtnEncryptAction implements ActionListener {

	private Main gui;
	private int count_enc = 0;
	private JPanel pn;
	private GridLayout grid;
	private JButton btnEncrypt;
	private Thread thread;
	private ICIA cia;

	
	public BtnEncryptAction(Main gui) {
		this.gui = gui;
		pn = this.gui.getPnListProcessEnc();
		grid = this.gui.getGrid_enc();
		btnEncrypt = this.gui.getBtnEncrypt();
		this.cia = new CIA();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (!isEmpty(gui.getTfInputEnc().getText(), gui.getTfOutputEnc().getText(), new String(gui.getTfPassword().getPassword()), gui.getTfPrivateKey().getText())) {
			btnEncrypt.setEnabled(false);
			thread = new Thread(doEncrypt);
			thread.start();
		}else{
			JOptionPane.showMessageDialog(gui, "The fields cannot be empty","Message", JOptionPane.INFORMATION_MESSAGE);
		}
	}

	private Runnable doEncrypt = new Runnable() {
		@Override
		public void run() {
			try {
				PrivateKey privateKey = getPrivateKey();
				if(privateKey!= null){
					File inputFile = new File(gui.getTfInputEnc().getText());
					String outFolder = gui.getTfOutputEnc().getText();
					if(inputFile.exists()){
						boolean isDirectory =inputFile.isDirectory(); 
						if(isDirectory){
							JRowItem rowHeader = new JRowItem();
							rowHeader.setFileName("-----------BEGIN----------");
							addCompsEnc(rowHeader);
							
							encryptFolder(privateKey, inputFile, outFolder);
							
							JRowItem rowFooter = new JRowItem();
							rowFooter.setFileName("-----------DONE----------");
							addCompsEnc(rowFooter);
						}else{
							JRowItem rowHeader = new JRowItem();
							rowHeader.setFileName("-----------BEGIN----------");
							addCompsEnc(rowHeader);
							File fileOut = new File(outFolder +"/" + inputFile.getName());
							if(!fileOut.getParentFile().exists())
								fileOut.getParentFile().mkdirs();
							encryptFile(privateKey, inputFile, fileOut);
							
							JRowItem rowFooter = new JRowItem();
							rowFooter.setFileName("-----------DONE----------");
							addCompsEnc(rowFooter);
						}
					}
					JOptionPane.showMessageDialog(gui, "Your file(s) is encrypted", "message", JOptionPane.INFORMATION_MESSAGE);
				}else{
					JOptionPane.showMessageDialog(gui, "Your private key file or your password is invalid","Message", JOptionPane.ERROR_MESSAGE);
				}
				btnEncrypt.setEnabled(true);
				thread.join();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};

	public PrivateKey getPrivateKey() {
		try {
			File file = new File(gui.getTfPrivateKey().getText());
			String prikey_name = file.getName();
			String prikey_pem = "privatekeypem.pem";
			String prikey_der = "privatekeyder.der";
			
			TerminalUtils.removePassPhrase(file.getParent(), prikey_name, prikey_pem, new String(gui.getTfPassword().getPassword()));
			TerminalUtils.convertPEMtoDER(file.getParent(), prikey_pem, prikey_der);
			
			PrivateKey privateKey = CAUtils.getPrivateKey(file.getParent() + "/" + prikey_der);
			
			TerminalUtils.removeFile(file.getParent()+"/"+prikey_pem);
			TerminalUtils.removeFile(file.getParent()+"/"+prikey_der);
			return privateKey;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	private void encryptFolder(PrivateKey prikey, File inputDirectory, String pathOut){
		File fileOut = new File(pathOut);
		if(inputDirectory.isDirectory()){
			fileOut.mkdirs();
		}
		
		if(inputDirectory.isFile()){
			encryptFile(prikey, inputDirectory, fileOut);
			
		}else if(inputDirectory.isDirectory()){
			File[] list = inputDirectory.listFiles();
			if(list.length!=0){
				for(File file : list){
					encryptFolder(prikey, file, pathOut+"/"+file.getName());
				}
			}
		}
	}
	
	private void encryptFile(PrivateKey prikey, File fileIn, File fileOut){
		JRowItem rowItem = new JRowItem();
		rowItem.setFileName(fileIn.getName());
		rowItem.setSize(new Dimension(530,rowItem.getHeight()));
		addCompsEnc(rowItem);
		cia.CIAEncrypter(fileIn, fileOut, prikey);
		rowItem.setPercent("encrypted");
		rowItem.revalidate();
	}
	
	private boolean isEmpty(String... values) {
		for (int i = 0; i < values.length; i++) {
			if (values[i].equals("")) {
				return true;
			}
		}
		return false;
	}

	private void addCompsEnc(JRowItem rowItem) {
		count_enc++;
		updateCapicityEnc();
		pn.add(rowItem);
		pn.revalidate();
		pn.scrollRectToVisible(new Rectangle(0,pn.getHeight(),10,10));
	}

	private void updateCapicityEnc() {
		if (count_enc > 9) {
			grid.setRows(grid.getRows() + 1);
		}
	}
}
